import asyncio
import datetime
import json

from app.api.generate.utils.generate_queue.queue_utils import send_queue_message
from app.db.session import SessionLocal
from app.models.generate import GenerateTextRecord
from app.api.generate.schemas import generate_text_schema

from app.utils.curd_base import ModelCRUD
from app.utils import security
from app.utils.custom_response import success_response
from fastapi import APIRouter, Query, Body, Path
from fastapi import Depends, Request
from sqlalchemy.orm import Session
from app.db.database import get_db
from app.models.system import Users
from typing import Any, Dict
from fastapi.encoders import jsonable_encoder
from app.utils.custom_exc import CustomException
from sqlalchemy import func, or_, not_

from app.utils.file_storage import get_storage_file, delete_storage_file
from app.utils.websocket_utils import publish_message


topic = "request_generate_text"


class GenerateTextRecordCRUD(ModelCRUD):
    model = GenerateTextRecord

    @staticmethod
    def serializer(queryset, only: tuple = (), date_format: str = None, datetime_format: str = None,
                   time_format: str = None):
        li = []
        for instance in queryset:
            dit = instance.to_dict(only=only, date_format=date_format, datetime_format=datetime_format, time_format=time_format)
            dit['user_nickname'] = instance.user.nickname if instance.user else None
            result_li = []
            for ins in instance.generate_text_image:
                result_dit = ins.to_dict(only=("id", "path", "text_id"), date_format=date_format, datetime_format=datetime_format, time_format=time_format)
                result_dit['path'] = get_storage_file(result_dit['path'])
                result_li.append(result_dit)
            dit['result'] = result_li
            # print(instance.user.id)
            li.append(dit)
        return li
        # return [instance.to_dict(only=only, date_format=date_format, datetime_format=datetime_format,
        #                          time_format=time_format) for instance in queryset]


router = APIRouter()


@router.post("/generate_text", summary="生成文本", response_model=generate_text_schema.GenerateTextRecordSchemaRes, name='生成文本')
async def generate_text(
        *,
        db: Session = Depends(get_db),
        req_data: generate_text_schema.GenerateTextRecordSchemaReq,
        current_user: Users = Depends(security.verify_access_token),
) -> Any:
    crud = GenerateTextRecordCRUD()
    req_data = jsonable_encoder(req_data)

    valid = generate_text_schema.GenerateTextRecordSchemaCreate.validate
    if isinstance(req_data.get('problem'), list):
        li = []
        problem_li = req_data.get('problem')
        for problem in problem_li:
            req_data['user_id'] = current_user.id
            req_data['problem'] = problem
            item = crud.create(db, data=valid(req_data))
            item_dict = item.to_dict(only=('id', 'user_id', 'problem', 'state', 'answer', 'answer_time', 'draw', 'publish'))
            item_dict['result'] = []
            item_dict['user_nickname'] = item.user.nickname if item.user else None
            li.append(item_dict)
            send_dict = {'record_id': item.id, 'problem': problem}
            send_queue_message(topic, send_dict)
            # ----------------------------------
        return success_response(data=li, message="批量生成中...")
    else:

        req_data['user_id'] = current_user.id
        item = crud.create(db, data=valid(req_data))
        item_dict = item.to_dict(only=('id', 'user_id', 'problem', 'state', 'answer', 'answer_time', 'draw', 'publish'))
        item_dict['result'] = []
        item_dict['user_nickname'] = item.user.nickname if item.user else None
        resp_data = item_dict
        send_dict = {'record_id': item.id, 'problem': req_data.get('problem')}
        send_queue_message(topic, send_dict)
        # -------------------------------

        return success_response(data=resp_data)


def filter_problem_answer(queryset, name, value):
    return queryset.filter(or_(GenerateTextRecord.answer.contains(value), GenerateTextRecord.problem.contains(value)))


able_filter_list = [
    {'name': 'searchinfo', 'label': '包含名字', 'type': str, 'method': filter_problem_answer, 'required': False},
    {'name': 'problem', 'source_filed': 'problem', 'lookup_expr': 'ic', 'label': '包含名字', 'type': str, 'method': None, 'required': False},
    {'name': 'user', 'source_filed': 'user_id', 'lookup_expr': 'eq', 'label': '等于', 'type': int},
]


@router.get("/get_generate_text_record", summary="获取生成文本记录", response_model=generate_text_schema.GenerateTextRecordSchemaRes, name='获取生成文本记录')
async def get_generate_text_record(
        request: Request,
        *,
        db: Session = Depends(get_db),
        page: int = Query(1, description='页码', ge=1),
        page_size: int = Query(10, description='页面大小', le=50, ge=1),
        current_user: Users = Depends(security.verify_access_token),

) -> Any:
    # print(request.query_params, request.query_params.get('name__ic'))
    # print(query_params, request)

    # able_search_list = ['problem__ic', 'user_id__eq']
    order_by_fields = ("-id",)
    crud = GenerateTextRecordCRUD()
    # queryset, total = crud.get_page_queryset(db, page=page, page_size=page_size, req_data=request.query_params, able_filter_list=able_filter_list, order_by_fields=order_by_fields)
    queryset = crud.get_all_queryset(db, req_data=request.query_params, able_filter_list=able_filter_list, order_by_fields=order_by_fields)

    queryset = queryset.filter(or_(GenerateTextRecord.state == 1, GenerateTextRecord.state == 2))

    queryset, total = crud.get_queryset_pagination(queryset, page=page, page_size=page_size)
    datetime_format = '%Y-%m-%d %H:%M:%S'
    items = crud.serializer(queryset, only=('id', 'user_id', 'problem', 'state', 'answer', 'answer_time', 'draw', 'publish', 'create_time'), datetime_format=datetime_format)
    resp_data = {
        "items": items,
        'total': total
    }
    return success_response(data=resp_data)


@router.post("/del_generate_text_record", summary="删除生成文本记录", response_model=generate_text_schema.GenerateTextRecordSchemaRes, name='删除生成文本记录')
async def del_generate_image(
        *,
        db: Session = Depends(get_db),
        req_data: generate_text_schema.GenerateTextRecordSchemaIDList,
        current_user: Users = Depends(security.verify_admin_permission),
) -> Any:
    crud = GenerateTextRecordCRUD()
    queryset = crud.get_all_queryset(db)
    req_data = jsonable_encoder(req_data)
    queryset = queryset.filter(crud.model.id.in_(req_data.get('id', [])))
    for instance in queryset:
        result = instance.generate_text_image
        for ins in result:
            delete_storage_file(ins.path)
    queryset.delete()
    db.commit()
    return success_response(data={}, message="删除成功")


@router.post("/generate_text_publish", summary="生成文本记录发布", response_model=generate_text_schema.GenerateTextRecordSchemaRes, name='生成文本记录发布')
async def generate_text_publish(
        *,
        db: Session = Depends(get_db),
        req_data: generate_text_schema.GenerateTextRecordSchemaIDList,
        current_user: Users = Depends(security.verify_admin_permission),
) -> Any:
    crud = GenerateTextRecordCRUD()
    queryset = crud.get_all_queryset(db)
    req_data = jsonable_encoder(req_data)
    queryset = queryset.filter(crud.model.id.in_(req_data.get('id', [])))
    queryset.update({GenerateTextRecord.publish: 1})
    db.commit()
    return success_response(data={}, message="发布成功")


@router.post("/generate_text_draw", summary="生成文本记录生成图片", response_model=generate_text_schema.GenerateTextRecordSchemaRes, name='生成文本记录生成图片')
async def generate_text_draw(
        *,
        db: Session = Depends(get_db),
        req_data: generate_text_schema.GenerateTextRecordSchemaIDList,
        current_user: Users = Depends(security.verify_admin_permission),
) -> Any:
    crud = GenerateTextRecordCRUD()
    queryset = crud.get_all_queryset(db)
    req_data = jsonable_encoder(req_data)
    queryset = queryset.filter(crud.model.id.in_(req_data.get('id', [])))
    for instance in queryset:
        pass
    queryset.update({GenerateTextRecord.draw: 1})
    db.commit()
    return success_response(data={}, message="生成中...")


